package com.blyat.xsoft.gateway.ribbon.router.database;

import com.blyat.xsoft.gateway.ribbon.router.RouteDefinitionLoader;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.context.ApplicationContext;

import java.net.URI;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Auther: syh
 * @Date: 2020/9/2
 * @Description: 定制的Route.肯定不如文本的json灵活。目前filters和predicates都有功能限制。
 */
public class DatabaseRouteDefinitionLoader implements RouteDefinitionLoader {

    private ApplicationContext context;

    private XSoftRouterService routerService;

    public DatabaseRouteDefinitionLoader(ApplicationContext context) {
        this.context = context;
        this.routerService = this.context.getBean(XSoftRouterService.class);
    }

    @Override
    public List<RouteDefinition> load() throws Exception {
        List<? extends XSoftRouter> routerList = routerService.getAvailableRouters();
        if (routerList != null && !routerList.isEmpty()) {
            return routerList.parallelStream().map(r -> {
                RouteDefinition router = new RouteDefinition();
                router.setId(r.getCode());
                router.setMetadata(buildMetadata(r));
                router.setFilters(buildFilters(r));
                router.setPredicates(buildPredicates(r));
                router.setUri(buildURI(r));
                router.setOrder(r.getOrder());
                return router;
            }).collect(Collectors.toList());
        }
        return null;
    }

    private Map<String, Object> buildMetadata(XSoftRouter router) {
        Map<String, Object> metadata = Maps.newHashMapWithExpectedSize(2);
        metadata.put("connect-timeout", router.getConnectTimeout());
        metadata.put("response-timeout", router.getResponseTimeout());
        return metadata;
    }

    private List<FilterDefinition> buildFilters(XSoftRouter router) {
        List<FilterDefinition> filterList = Lists.newArrayListWithExpectedSize(2);
        FilterDefinition filter = new FilterDefinition();
        filter.setName("Retry");
        filter.setArgs(Collections.singletonMap("retries", String.valueOf(router.getRetry())));
        filterList.add(filter);


        filter = new FilterDefinition();
        filter.setName("StripPrefix");
        filter.setArgs(Collections.singletonMap("parts", String.valueOf(router.getStripPrefix())));
        filterList.add(filter);
        return filterList;
    }

    private List<PredicateDefinition> buildPredicates(XSoftRouter router) {
        List<PredicateDefinition> predicateList = Lists.newArrayListWithExpectedSize(2);
        PredicateDefinition predicate = new PredicateDefinition();
        predicate.setName("Path");
        predicate.setArgs(Collections.singletonMap("pattern", String.format("/%s%s", router.getPrefix(), router.getPath())));
        predicateList.add(predicate);
        return predicateList;
    }

    private URI buildURI(XSoftRouter router) {
        String url = router.getProxyUri();
        if (!router.getProxyUri().startsWith(router.getProtocol())) {
            url = String.format("%s://%s", router.getProtocol(), router.getProxyUri());
        }
        return URI.create(url);
    }
}
